// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using Microsoft.EntityFrameworkCore.Metadata.Builders;

namespace Microsoft.EntityFrameworkCore.Metadata
{
    /// <summary>
    ///     <para>
    ///         Represents a scalar property of an entity.
    ///     </para>
    ///     <para>
    ///         This interface is used during model creation and allows the metadata to be modified.
    ///         Once the model is built, <see cref="IProperty" /> represents a read-only view of the same metadata.
    ///     </para>
    /// </summary>
    public interface IConventionProperty : IProperty, IConventionPropertyBase
    {
        /// <summary>
        ///     Gets the builder that can be used to configure this property.
        /// </summary>
        IConventionPropertyBuilder Builder { get; }

        /// <summary>
        ///     Gets the type that this property belongs to.
        /// </summary>
        new IConventionEntityType DeclaringEntityType { get; }

        /// <summary>
        ///     Returns the configuration source for this property.
        /// </summary>
        /// <returns> The configuration source. </returns>
        ConfigurationSource GetConfigurationSource();

        /// <summary>
        ///     Returns the configuration source for <see cref="IPropertyBase.ClrType" />.
        /// </summary>
        /// <returns> The configuration source for <see cref="IPropertyBase.ClrType" />. </returns>
        ConfigurationSource? GetTypeConfigurationSource();

        /// <summary>
        ///     Sets a value indicating whether this property can contain <c>null</c>.
        /// </summary>
        /// <param name="nullable">
        ///     A value indicating whether this property can contain <c>null</c>.
        ///     <c>null</c> to reset to default.
        /// </param>
        /// <param name="fromDataAnnotation"> Indicates whether the configuration was specified using a data annotation. </param>
        void SetIsNullable(bool? nullable, bool fromDataAnnotation = false);

        /// <summary>
        ///     Returns the configuration source for <see cref="IProperty.IsNullable" />.
        /// </summary>
        /// <returns> The configuration source for <see cref="IProperty.IsNullable" />. </returns>
        ConfigurationSource? GetIsNullableConfigurationSource();

        /// <summary>
        ///     Sets a value indicating when a value for this property will be generated by the database. Even when the
        ///     property is set to be generated by the database, EF may still attempt to save a specific value (rather than
        ///     having one generated by the database) when the entity is added and a value is assigned, or the property is
        ///     marked as modified for an existing entity. See <see cref="PropertyExtensions.GetBeforeSaveBehavior" /> and
        ///     <see cref="PropertyExtensions.GetAfterSaveBehavior" /> for more information.
        /// </summary>
        /// <param name="valueGenerated">
        ///     A value indicating when a value for this property will be generated by the database.
        ///     <c>null</c> to reset to default.
        /// </param>
        /// <param name="fromDataAnnotation"> Indicates whether the configuration was specified using a data annotation. </param>
        void SetValueGenerated(ValueGenerated? valueGenerated, bool fromDataAnnotation = false);

        /// <summary>
        ///     Returns the configuration source for <see cref="IProperty.ValueGenerated" />.
        /// </summary>
        /// <returns> The configuration source for <see cref="IProperty.ValueGenerated" />. </returns>
        ConfigurationSource? GetValueGeneratedConfigurationSource();

        /// <summary>
        ///     Sets a value indicating whether this property is used as a concurrency token. When a property is configured
        ///     as a concurrency token the value in the database will be checked when an instance of this entity type
        ///     is updated or deleted during <see cref="DbContext.SaveChanges()" /> to ensure it has not changed since
        ///     the instance was retrieved from the database. If it has changed, an exception will be thrown and the
        ///     changes will not be applied to the database.
        /// </summary>
        /// <param name="concurrencyToken">
        ///     Sets a value indicating whether this property is used as a concurrency token.
        ///     <c>null</c> to reset to default.
        /// </param>
        /// <param name="fromDataAnnotation"> Indicates whether the configuration was specified using a data annotation. </param>
        void SetIsConcurrencyToken(bool? concurrencyToken, bool fromDataAnnotation = false);

        /// <summary>
        ///     Returns the configuration source for <see cref="IProperty.IsConcurrencyToken" />.
        /// </summary>
        /// <returns> The configuration source for <see cref="IProperty.IsConcurrencyToken" />. </returns>
        ConfigurationSource? GetIsConcurrencyTokenConfigurationSource();
    }
}
